#include "8bit.h"
#include "koi8ucvt.h"

using namespace std;


static const wchar_t koi2ucs[] = {
	0x2500, 0x2502, 0x250C, 0x2510, 0x2514, 0x2518, 0x251C, 0x2524,
	0x252C, 0x2534, 0x253C, 0x2580, 0x2584, 0x2588, 0x258C, 0x2590,
	0x2591, 0x2592, 0x2593, 0x2320, 0x25A0, 0x2219, 0x221A, 0x2248,
	0x2264, 0x2265, 0x00A0, 0x2321, 0x00B0, 0x00B2, 0x00B7, 0x00F7,
	0x2550, 0x2551, 0x2552, 0x0451, 0x0454, 0x2554, 0x0456, 0x0457,
	0x2557, 0x2558, 0x2559, 0x255A, 0x255B, 0x0491, 0x255D, 0x255E,
	0x255F, 0x2560, 0x2561, 0x0401, 0x0404, 0x2563, 0x0406, 0x0407,
	0x2566, 0x2567, 0x2568, 0x2569, 0x256A, 0x0490, 0x256C, 0x00A9,
	0x044E, 0x0430, 0x0431, 0x0446, 0x0434, 0x0435, 0x0444, 0x0433,
	0x0445, 0x0438, 0x0439, 0x043A, 0x043B, 0x043C, 0x043D, 0x043E,
	0x043F, 0x044F, 0x0440, 0x0441, 0x0442, 0x0443, 0x0436, 0x0432,
	0x044C, 0x044B, 0x0437, 0x0448, 0x044D, 0x0449, 0x0447, 0x044A,
	0x042E, 0x0410, 0x0411, 0x0426, 0x0414, 0x0415, 0x0424, 0x0413,
	0x0425, 0x0418, 0x0419, 0x041A, 0x041B, 0x041C, 0x041D, 0x041E,
	0x041F, 0x042F, 0x0420, 0x0421, 0x0422, 0x0423, 0x0416, 0x0412,
	0x042C, 0x042B, 0x0417, 0x0428, 0x042D, 0x0429, 0x0427, 0x042A
};

static const struct cw ucs2koi[] = {
	{0x9A, 0x00A0}, {0xBF, 0x00A9}, {0x9C, 0x00B0}, {0x9D, 0x00B2},
	{0x9E, 0x00B7}, {0x9F, 0x00F7}, {0xB3, 0x0401}, {0xB4, 0x0404},
	{0xB6, 0x0406}, {0xB7, 0x0407}, {0xE1, 0x0410}, {0xE2, 0x0411},
	{0xF7, 0x0412}, {0xE7, 0x0413}, {0xE4, 0x0414}, {0xE5, 0x0415},
	{0xF6, 0x0416}, {0xFA, 0x0417}, {0xE9, 0x0418}, {0xEA, 0x0419},
	{0xEB, 0x041A}, {0xEC, 0x041B}, {0xED, 0x041C}, {0xEE, 0x041D},
	{0xEF, 0x041E}, {0xF0, 0x041F}, {0xF2, 0x0420}, {0xF3, 0x0421},
	{0xF4, 0x0422}, {0xF5, 0x0423}, {0xE6, 0x0424}, {0xE8, 0x0425},
	{0xE3, 0x0426}, {0xFE, 0x0427}, {0xFB, 0x0428}, {0xFD, 0x0429},
	{0xFF, 0x042A}, {0xF9, 0x042B}, {0xF8, 0x042C}, {0xFC, 0x042D},
	{0xE0, 0x042E}, {0xF1, 0x042F}, {0xC1, 0x0430}, {0xC2, 0x0431},
	{0xD7, 0x0432}, {0xC7, 0x0433}, {0xC4, 0x0434}, {0xC5, 0x0435},
	{0xD6, 0x0436}, {0xDA, 0x0437}, {0xC9, 0x0438}, {0xCA, 0x0439},
	{0xCB, 0x043A}, {0xCC, 0x043B}, {0xCD, 0x043C}, {0xCE, 0x043D},
	{0xCF, 0x043E}, {0xD0, 0x043F}, {0xD2, 0x0440}, {0xD3, 0x0441},
	{0xD4, 0x0442}, {0xD5, 0x0443}, {0xC6, 0x0444}, {0xC8, 0x0445},
	{0xC3, 0x0446}, {0xDE, 0x0447}, {0xDB, 0x0448}, {0xDD, 0x0449},
	{0xDF, 0x044A}, {0xD9, 0x044B}, {0xD8, 0x044C}, {0xDC, 0x044D},
	{0xC0, 0x044E}, {0xD1, 0x044F}, {0xA3, 0x0451}, {0xA4, 0x0454},
	{0xA6, 0x0456}, {0xA7, 0x0457}, {0xBD, 0x0490}, {0xAD, 0x0491},
	{0x95, 0x2219}, {0x96, 0x221A}, {0x97, 0x2248}, {0x98, 0x2264},
	{0x99, 0x2265}, {0x93, 0x2320}, {0x9B, 0x2321}, {0x80, 0x2500},
	{0x81, 0x2502}, {0x82, 0x250C}, {0x83, 0x2510}, {0x84, 0x2514},
	{0x85, 0x2518}, {0x86, 0x251C}, {0x87, 0x2524}, {0x88, 0x252C},
	{0x89, 0x2534}, {0x8A, 0x253C}, {0xA0, 0x2550}, {0xA1, 0x2551},
	{0xA2, 0x2552}, {0xA5, 0x2554}, {0xA8, 0x2557}, {0xA9, 0x2558},
	{0xAA, 0x2559}, {0xAB, 0x255A}, {0xAC, 0x255B}, {0xAE, 0x255D},
	{0xAF, 0x255E}, {0xB0, 0x255F}, {0xB1, 0x2560}, {0xB2, 0x2561},
	{0xB5, 0x2563}, {0xB8, 0x2566}, {0xB9, 0x2567}, {0xBA, 0x2568},
	{0xBB, 0x2569}, {0xBC, 0x256A}, {0xBE, 0x256C}, {0x8B, 0x2580},
	{0x8C, 0x2584}, {0x8D, 0x2588}, {0x8E, 0x258C}, {0x8F, 0x2590},
	{0x90, 0x2591}, {0x91, 0x2592}, {0x92, 0x2593}, {0x94, 0x25A0}
};


codecvt_base::result koi8ucvt::do_in(mbstate_t&, const char* from,
  const char* from_end, const char*& from_next, wchar_t* to,
  wchar_t* to_limit, wchar_t*& to_next) const
{
	return ::do_in(from, from_end, from_next, to, to_limit, to_next, 0x80,
	  koi2ucs) ? codecvt_base::error : codecvt_base::ok;
}

codecvt_base::result koi8ucvt::do_out(mbstate_t&, const wchar_t* from,
  const wchar_t* from_end, const wchar_t*& from_next, char* to,
  char* to_limit, char*& to_next) const
{
	return ::do_out(from, from_end, from_next, to, to_limit, to_next, 0x80,
	  ucs2koi, sizeof(ucs2koi)) ? codecvt_base::error : codecvt_base::ok;
}

codecvt_base::result koi8ucvt::do_unshift(mbstate_t&, char* to, char*,
  char*& to_next) const
{
	to_next = to;

	return codecvt_base::noconv;
}
